using System;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Common;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.Mocks;
using Microsoft.WowAddonStudio.Lua.RuntimeService.Tests.WowBench;
using Microsoft.WowAddonStudio.Lua.RuntimeService.WowBench.Resolvers;
using Microsoft.WowAddonStudio.Services;
using Microsoft.WowAddonStudio.Tests.Common.Mocks;
using NUnit.Framework;

namespace Microsoft.WowAddonStudio.Lua.RuntimeService.Tests
{
	[TestFixture]
	public class LuaRuntimeExceptionTest : WoWBenchTestBase
	{
		private ILuaRuntime runtime;

		#region SetUp

		/// <summary>
		/// Tests the fixture set up.
		/// </summary>
		[TestFixtureSetUp]
		public override void TestFixtureSetUp()
		{
			SimpleTestServiceLocator.Register<IAddonStudioSettings>(new MockAddonStudioSettings(wowBenchPath));
			runtime = new LuaRuntime(Provider, new ResolverFactory(Provider), new MockShellHostFactory());
		}

		#endregion

		#region TearDown

		/// <summary>
		/// Tests the fixture tear down.
		/// </summary>
		public override void TestFixtureTearDown()
		{
			base.TestFixtureTearDown();
			runtime.Dispose();
			Environment.CurrentDirectory = savedPath;
		}

		#endregion

		#region Tests

		/// <summary>
		/// Test_s the base lua runtime exception.
		/// </summary>
		[Test(Description = "")]
		public void Test_BaseLuaRuntimeException()
		{
			var exception = new LuaRuntimeException(runtime);
			using (Stream serializationStream = new MemoryStream())
			{
				var formatter = new BinaryFormatter();
				formatter.Serialize(serializationStream, exception);
				serializationStream.Position = 0;
				exception = formatter.Deserialize(serializationStream) as LuaRuntimeException;
			}
			Assert.IsNotNull(exception);
			Console.WriteLine(exception.RuntimeName);
			Assert.AreEqual(runtime.Name, exception.RuntimeName);
		}

		/// <summary>
		/// Test_s the lua runtime service not found exception.
		/// </summary>
		[Test(Description = "")]
		public void Test_LuaRuntimeServiceNotFoundException()
		{
			var exception = new LuaRuntimeServiceNotFoundException(runtime);
			using (Stream serializationStream = new MemoryStream())
			{
				var formatter = new BinaryFormatter();
				formatter.Serialize(serializationStream, exception);
				serializationStream.Position = 0;
				exception = formatter.Deserialize(serializationStream) as LuaRuntimeServiceNotFoundException;
			}
			Assert.IsNotNull(exception);
			Console.WriteLine(exception.RuntimeName);
			Assert.AreEqual(runtime.Name, exception.RuntimeName);
			Assert.IsNotNull(exception.InnerException);
			Assert.IsInstanceOfType(typeof(InvalidOperationException), exception.InnerException);
			Assert.IsNotNull(exception.InnerException.InnerException);
			Assert.IsInstanceOfType(typeof(NullReferenceException), exception.InnerException.InnerException);
		}

		/// <summary>
		/// Test_s the runtime shell host exception.
		/// </summary>
		[Test(Description = "")]
		public void Test_RuntimeShellHostException()
		{
			runtime.Load(LuaRuntimeType.LuaInterpreter);
			var exception = new RuntimeShellHostException(runtime);
			using (Stream serializationStream = new MemoryStream())
			{
				var formatter = new BinaryFormatter();
				formatter.Serialize(serializationStream, exception);
				serializationStream.Position = 0;
				exception = formatter.Deserialize(serializationStream) as RuntimeShellHostException;
			}
			Assert.IsNotNull(exception);
			Console.WriteLine(exception.RuntimeName);
			Assert.AreEqual(runtime.Name, exception.RuntimeName);
			Assert.IsNotNull(runtime.RuntimeShellHost);
			Assert.IsNotNull(exception.ShellHost);
			Assert.AreEqual(runtime.RuntimeShellHost.ShellName, exception.ShellHost.ShellName);
			Console.WriteLine("Message: {0}", exception.Message);
		}

		/// <summary>
		/// Test_s the runtime shell host not found exception.
		/// </summary>
		[Test(Description = "")]
		public void Test_RuntimeShellHostNotFoundException()
		{
			runtime.Load(LuaRuntimeType.LuaInterpreter);
			var exception = new RuntimeShellHostNotFoundException(runtime);
			using (Stream serializationStream = new MemoryStream())
			{
				var formatter = new BinaryFormatter();
				formatter.Serialize(serializationStream, exception);
				serializationStream.Position = 0;
				exception = formatter.Deserialize(serializationStream) as RuntimeShellHostNotFoundException;
			}
			Assert.IsNotNull(exception);
			Console.WriteLine(exception.RuntimeName);
			Assert.AreEqual(runtime.Name, exception.RuntimeName);
			Assert.IsNotNull(runtime.RuntimeShellHost);
			Assert.IsNotNull(exception.ShellHost);
			Assert.AreEqual(runtime.RuntimeShellHost.ShellName, exception.ShellHost.ShellName);
			Assert.IsNotNull(exception.InnerException);
			Assert.IsInstanceOfType(typeof(InvalidOperationException), exception.InnerException);
			Assert.IsNotNull(exception.InnerException.InnerException);
			Assert.IsInstanceOfType(typeof(NullReferenceException), exception.InnerException.InnerException);
			Console.WriteLine("Message: {0}", exception.Message);
		}

		/// <summary>
		/// Test_s the lua runtime initialization exception.
		/// </summary>
		[Test(Description = "")]
		public void Test_LuaRuntimeInitializationException()
		{
			runtime.Load(LuaRuntimeType.LuaInterpreter);
			var exception = new LuaRuntimeInitializationException(runtime, "provider");
			using (Stream serializationStream = new MemoryStream())
			{
				var formatter = new BinaryFormatter();
				formatter.Serialize(serializationStream, exception);
				serializationStream.Position = 0;
				exception = formatter.Deserialize(serializationStream) as LuaRuntimeInitializationException;
			}
			Assert.IsNotNull(exception);
			Console.WriteLine(exception.RuntimeName);
			Assert.AreEqual(runtime.Name, exception.RuntimeName);
			Assert.IsNotNull(runtime.RuntimeShellHost);
			Assert.IsNotNull(exception.InnerException);
			Assert.IsInstanceOfType(typeof(ArgumentNullException), exception.InnerException);
			Assert.AreEqual("provider", exception.Argument);
			Console.WriteLine("Message: {0}", exception.Message);
		}

		#endregion
	}
}